home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue31 / extend / ODSXP.PAS next >
Encoding:
Pascal/Delphi Source File  |  1997-07-03  |  19.6 KB  |  730 lines

  1. { Created: 1997-02-14 by Berend  (c) 1997 by ASC
  2.  
  3. Unit which makes implementing SQL Server extended stored
  4. procedures a breeze.
  5.  
  6. $Revision: 3 $
  7.  
  8.  
  9. How to create an extended stored procedure:
  10. 1. Create a new class based TSQLXProc and override its
  11.    Execute method.
  12.  
  13. 2. Always create the following prototype
  14.  
  15.      function xp_demo(srvproc: PSRV_PROC): SRVRETCODE;
  16.      var
  17.        xp: TSQLXProc;
  18.      begin
  19.        xp := TMySQLXProc.Create(srvproc, ExpectedParams);
  20.        Result := xp.Run;
  21.        xp.Free;
  22.      end;
  23.  
  24. 3. export xp_demo.
  25.  
  26.  
  27. Notes:
  28. - lots of api calls not supported, but most of them you
  29.   don't need for extended stored procedures. The few that
  30.   remain are easy to add. 
  31. - don't trust my money datatype... I'm not sure the 8 byte
  32.   calculations are done corretly (they seem to be, but you
  33.   never know)
  34. - numeric datatype only supported upto a nine digit precision
  35.   (that is including the fractional part) so largest value
  36.   is 999,999,999,0
  37. - not supported datatypes: binary, varbinary, timestamp,
  38.   text/image
  39.  
  40.  
  41.  
  42. $History: Odsxp.pas $
  43.  * 
  44.  * *****************  Version 3  *****************
  45.  * User: Berend       Date: 97-04-24   Time: 21:25
  46.  * Updated in $/ASC sources
  47.  * Fix bug: error is returned when ok and vice versa
  48.  * 
  49.  * *****************  Version 1  *****************
  50.  * User: Berend       Date: 97-02-18   Time: 20:06
  51.  * Created in $/ASC sources
  52.  * Extended procedures for Delphi
  53. }
  54.  
  55.  
  56. {$LONGSTRINGS ON}
  57.  
  58.  
  59. unit Odsxp;
  60.  
  61. interface
  62.  
  63. uses
  64.   Windows,
  65.   SysUtils,
  66.   Classes;
  67.  
  68.  
  69. { type definitions }
  70. type
  71.   Int8 = shortint;
  72.   UInt8 = byte;
  73.   Int16 = smallint;
  74.   Int32 = longint;
  75.   UInt16 = word;
  76.   UInt32 = longint;
  77.  
  78.  
  79.  
  80. { translated parts from Srv*.h }
  81.  
  82. const
  83.   SUCCEED = 0;          { Successful return value   }
  84.   FAIL = 1;             { Unsuccessful return value }
  85.  
  86. type
  87.   SRVRETCODE = Int32;        { SUCCEED or FAIL }
  88.  
  89. const
  90.   SRV_NULLTERM = -1;    { Indicates a null terminated string }
  91.  
  92. {  Done packet status fields. }
  93. const
  94.   SRV_DONE_FINAL        = $0000;
  95.   SRV_DONE_MORE         = $0001;
  96.   SRV_DONE_ERROR        = $0002;
  97.   SRV_DONE_INXACT       = $0004;
  98.   SRV_DONE_PROC         = $0008;
  99.   SRV_DONE_COUNT        = $0010;
  100.   SRV_DONE_ATTN         = $0020;
  101.   SRV_DONE_RPC_IN_BATCH = $0080;
  102.  
  103.  
  104. type
  105.   PSRV_PROC = pointer;
  106.  
  107. {  Message types }
  108. const
  109.   SRV_MSG_INFO = 1;
  110.   SRV_MSG_ERROR = 2;
  111.  
  112. { define srv_symbol() SRV_ERRORs }
  113. const
  114.   SRV_ENO_OS_ERR = 0;
  115.   SRV_INFO = 1;
  116.   SRV_FATAL_PROCESS = 10;
  117.   SRV_FATAL_SERVER = 19;
  118.  
  119. {  TDS tokens }
  120. const
  121.   SRV_TDS_NULL         = $1f;     { Null parameter from server }
  122.   SRV_TDS_IMAGE        = $22;
  123.   SRV_TDS_TEXT         = $23;
  124.   SRV_TDS_VARBINARY    = $25;
  125.   SRV_TDS_INTN         = $26;
  126.   SRV_TDS_VARCHAR      = $27;
  127.   SRV_TDS_BINARY       = $2d;
  128.   SRV_TDS_CHAR         = $2f;
  129.   SRV_TDS_INT1         = $30;
  130.   SRV_TDS_BIT          = $32;
  131.   SRV_TDS_INT2         = $34;
  132.   SRV_TDS_DECIMAL      = $37;
  133.   SRV_TDS_INT4         = $38;
  134.   SRV_TDS_DATETIM4     = $3a;
  135.   SRV_TDS_FLT4         = $3b;
  136.   SRV_TDS_MONEY        = $3c;
  137.   SRV_TDS_DATETIME     = $3d;
  138.   SRV_TDS_FLT8         = $3e;
  139.   SRV_TDS_NUMERIC      = $3f;
  140.   SRV_TDS_DECIMALN     = $6a;
  141.   SRV_TDS_NUMERICN     = $6c;
  142.   SRV_TDS_FLTN         = $6d;
  143.   SRV_TDS_MONEYN       = $6e;
  144.   SRV_TDS_DATETIMN     = $6f;
  145.   SRV_TDS_OFFSET       = $78;
  146.   SRV_TDS_RETURNSTATUS = $79;
  147.   SRV_TDS_MONEY4       = $7a;
  148.   SRV_TDS_PROCID       = $7c;
  149.   SRV_TDS_COLNAME      = $a0;
  150.   SRV_TDS_COLFMT       = $a1;
  151.   SRV_TDS_TABNAME      = $a4;
  152.   SRV_TDS_COLINFO      = $a5;
  153.   SRV_TDS_ORDER        = $a9;
  154.   SRV_TDS_ERROR        = $aa;
  155.   SRV_TDS_INFO         = $ab;
  156.   SRV_TDS_RETURNVALUE  = $ac;
  157.   SRV_TDS_LOGIN        = $ad;
  158.   SRV_TDS_CONTROL      = $ae;
  159.   SRV_TDS_ROW          = $d1;
  160.   SRV_TDS_ENVCHANGE    = $e3;
  161.   SRV_TDS_DONE         = $fd;
  162.   SRV_TDS_DONEPROC     = $fe;
  163.   SRV_TDS_DONEINPROC   = $ff;
  164.  
  165. { server types }
  166. const
  167.   SRVNULL              = SRV_TDS_NULL; { Null parameter from server }
  168.   SRVIMAGE             = SRV_TDS_IMAGE;
  169.   SRVTEXT              = SRV_TDS_TEXT;
  170.   SRVVARBINARY         = SRV_TDS_VARBINARY;
  171.   SRVINTN              = SRV_TDS_INTN;
  172.   SRVVARCHAR           = SRV_TDS_VARCHAR;
  173.   SRVBINARY            = SRV_TDS_BINARY;
  174.   SRVCHAR              = SRV_TDS_CHAR;
  175.   SRVINT1              = SRV_TDS_INT1;
  176.   SRVBIT               = SRV_TDS_BIT;
  177.   SRVINT2              = SRV_TDS_INT2;
  178.   SRVDECIMAL           = SRV_TDS_DECIMAL;
  179.   SRVINT4              = SRV_TDS_INT4;
  180.   SRVNUMERIC           = SRV_TDS_NUMERIC;
  181.   SRVFLTN              = SRV_TDS_FLTN;
  182.   SRVMONEYN            = SRV_TDS_MONEYN;
  183.   SRVDATETIMN          = SRV_TDS_DATETIMN;
  184.  
  185.  
  186.  
  187. { DB-Library datatypes (mainly taken from SQLfront.h) }
  188. const
  189.   DBMAXCHAR = 256;
  190.  
  191.   MAXNUMERICLEN = 16;
  192.   MAXNUMERICDIG = 38;
  193.   DEFAULTPRECISION = 18;
  194.   DEFAULTSCALE = 0;
  195.  
  196. type
  197.   DBCHAR = AnsiChar;
  198.   PDBCHAR = PAnsiChar;
  199.   DBBINARY = UInt8;
  200.   DBTINYINT = UInt8;
  201.   DBUSMALLINT = Int16;
  202.   DBUSSMALLINT = UInt16;
  203.   DBINT = Int32;
  204.   DBFLT8 = double;
  205.   DBBIT = UInt8;
  206.   DBBOOL = UInt8;
  207.   DBFLT4 = single;
  208.   DBMONEY4 = Int32;
  209.   DBMONEY = record
  210.     mnyhigh: DBINT;
  211.     mnylow: UInt32;
  212.   end;
  213.   DBDATETIM4 = record
  214.          numdays: UInt16;   { No of days since Jan-1-1900    }
  215.       nummins: UInt16;   { No. of minutes since midnight  }
  216.   end;
  217.   DBDATETIME = record
  218.     dtdays: DBINT;      { number of days since 1/1/1900 }
  219.     dttime: UInt32;     { number 300th second since mid }
  220.   end;
  221.   DBNUMERIC = record
  222.     precision,
  223.     scale: UInt8;
  224.     sign: ByteBool;
  225.     val: array[0..MAXNUMERICLEN] of Uint8;
  226.   end;
  227.  
  228.  
  229. { Extended procedure error codes }
  230. const
  231.   SRV_MAXERROR = 20000;
  232.  
  233.  
  234. { srvapi.h }
  235.  
  236. function srv_describe(
  237.            srvproc: PSRV_PROC;
  238.            colnumber: integer;
  239.            columnname: PDBCHAR;
  240.            namelen: integer;
  241.            desttype,
  242.            destlen,
  243.            srctype,
  244.            srclen: DBINT;
  245.            srcdata: pointer): integer; far; cdecl;
  246.  
  247. function srv_paramdata(
  248.            srvproc: PSRV_PROC;
  249.            n: integer): pointer; far; cdecl;
  250.  
  251. function srv_paramlen(
  252.            srvproc: PSRV_PROC;
  253.            n: integer): integer; far; cdecl;
  254.  
  255. function srv_parammaxlen(
  256.            srvproc: PSRV_PROC;
  257.            n: integer): integer; far; cdecl;
  258.  
  259. function srv_paramname(
  260.            srvproc: PSRV_PROC;
  261.            n: integer;
  262.            len: integer): PDBCHAR; far; cdecl;
  263.  
  264. function srv_paramnumber(
  265.            srvproc: PSRV_PROC;
  266.            name: PDBCHAR;
  267.            len: integer): integer; far; cdecl;
  268.  
  269. function srv_paramset(
  270.            srvproc: PSRV_PROC;
  271.            n: integer;
  272.            data: pointer;
  273.            len: integer): integer; far; cdecl;
  274.  
  275. function srv_paramstatus(
  276.            srvproc: PSRV_PROC;
  277.            n: integer): integer; far; cdecl;
  278.  
  279. function srv_paramtype(
  280.            srvproc: PSRV_PROC;
  281.            n: integer): integer; far; cdecl;
  282.  
  283. function srv_rpcparams(
  284.            srvproc: PSRV_PROC): integer; far; cdecl;
  285.  
  286. function srv_senddone(
  287.            srvproc: PSRV_PROC;
  288.            status: DBUSMALLINT;
  289.            curcmd: DBUSMALLINT;
  290.            count: DBINT): integer; far; cdecl;
  291.  
  292. function srv_sendrow(
  293.            srvproc: PSRV_PROC): integer; far; cdecl;
  294.  
  295. function srv_sendmsg(
  296.            srvproc: PSRV_PROC;
  297.            msgtype: integer;
  298.            msgnum: DBINT;
  299.            msgclass: DBTINYINT;
  300.            state: DBTINYINT;
  301.            rpcname: PDBCHAR;
  302.            rpcnamelen: integer;
  303.            linenum: DBUSMALLINT;
  304.            message: PDBCHAR;
  305.            msglen: integer): integer; far; cdecl;
  306.  
  307.  
  308.  
  309.  
  310. { the XP class }
  311.  
  312. const
  313.   PARAM_ERROR = SRV_MAXERROR + 1;
  314.  
  315. type
  316.   TSQLXProc = class
  317.   protected
  318.     srvproc: PSRV_PROC;
  319.     ExpectedParamCount: integer;  { -1 = no check done }
  320.     LastCol: cardinal;
  321.     RowCount: cardinal;           { set to number of rows you return }
  322.     function  GetParamCount: cardinal;
  323.     function  GetParam(Index: integer): Variant;
  324.     function  GetParamByName(Name: string): Variant;
  325.     procedure SetParam(Index: integer; const Value: Variant);
  326.     procedure SetParamByName(Name: string; const Value: Variant);
  327.   public
  328.     constructor Create(asrvproc: PSRV_PROC; AParamCount: integer);
  329.     procedure DescribeColumn(const Name: string;
  330.                              desttype, destlen,
  331.                              srctype, srclen: integer;
  332.                              srcdata:  pointer);
  333.     function Execute: Boolean; virtual; abstract;
  334.     function Run: SRVRETCODE;
  335.     procedure SendRow;
  336.     procedure SendErrorMsg(const Msg: string);
  337.     procedure SendInfoMsg(const Msg: string);
  338.     property ParamCount: cardinal read GetParamCount;
  339.     property Params[Index: integer]: Variant read GetParam write SetParam;
  340.     property ParamByName[Name: string]: Variant read GetParamByName write SetParamByName; default;
  341.   end;
  342.  
  343.  
  344.  
  345. implementation
  346.  
  347. {$IFDEF Debug}
  348. uses
  349.   BBDebug;
  350. {$ENDIF}
  351.  
  352.  
  353. const
  354.   opends = 'opends60.dll';
  355.  
  356.  
  357. function srv_describe;       external opends name 'srv_describe';
  358. function srv_paramdata;      external opends name 'srv_paramdata';
  359. function srv_paramlen;       external opends name 'srv_paramlen';
  360. function srv_parammaxlen;    external opends name 'srv_parammaxlen';
  361. function srv_paramname;      external opends name 'srv_paramname';
  362. function srv_paramnumber;    external opends name 'srv_paramnumber';
  363. function srv_paramset;       external opends name 'srv_paramset';
  364. function srv_paramstatus;    external opends name 'srv_paramstatus';
  365. function srv_paramtype;      external opends name 'srv_paramtype';
  366. function srv_rpcparams;      external opends name 'srv_rpcparams';
  367. function srv_senddone;       external opends name 'srv_senddone';
  368. function srv_sendrow;        external opends name 'srv_sendrow';
  369. function srv_sendmsg;        external opends name 'srv_sendmsg';
  370.  
  371.  
  372.  
  373. { TSQLXProc }
  374.  
  375. constructor TSQLXProc.Create(asrvproc: PSRV_PROC; AParamCount: integer);
  376. begin
  377.   inherited Create;
  378.   srvproc := asrvproc;
  379.   ExpectedParamCount := AParamCount;
  380. end;
  381.  
  382.  
  383. procedure TSQLXProc.DescribeColumn(
  384.   const Name: string;
  385.   desttype, destlen,
  386.   srctype, srclen: integer;
  387.   srcdata:  pointer);
  388. begin
  389.   LastCol := srv_describe(srvproc, LastCol+1, PChar(Name), SRV_NULLTERM,
  390.                            desttype, destlen, srctype, srclen, srcdata);
  391.   if LastCol = 0 then
  392.     raise Exception.Create('srv_describe failed.');
  393. end;
  394.  
  395.  
  396. function TSQLXProc.GetParamCount: cardinal;
  397. var
  398.   params: integer;
  399. begin
  400.   params := srv_rpcparams(srvproc);
  401.   if params < 0
  402.     then  Result := 0
  403.     else  Result := params;
  404. end;
  405.  
  406.  
  407. function TSQLXProc.GetParam(Index: integer): Variant;
  408. var
  409.   p: pointer;
  410.   paramlen: integer;
  411.   buf: array[0..DBMAXCHAR] of char;
  412.   numeric: DBNUMERIC;
  413.   l: longint;
  414.   s: string;
  415.   dbdt: dBDATETIME;
  416.   dbdt4: dBDATETIM4;
  417.   dt: TDateTime;
  418.   money4: DBMONEY4;
  419.   money: DBMONEY;
  420.   dc: comp;
  421.   dc2: comp;
  422. begin
  423.   p := srv_paramdata(srvproc, Index);
  424.   if p = nil
  425.     then  Result := Null
  426.     else  begin
  427.       paramlen := srv_paramlen(srvproc, Index);
  428. {$IFDEF Debug}
  429.       BBWrite('paramlen = ' + IntToStr(paramlen) + ' -- TSQLXProc.GetParam --');
  430. {$ENDIF}
  431.       case srv_paramtype(srvproc, Index) of
  432.         SRVNULL: Result := Null;
  433.         SRVVARCHAR,
  434.         SRVCHAR:
  435.           begin
  436.             Move(p^, buf, paramlen);
  437.             buf[paramlen] := #0;
  438.             Result := StrPas(@buf);
  439.           end;
  440.         SRVINTN:
  441.           begin
  442.             case paramlen of
  443.               1: Result := Int8(p^);
  444.               2: Result := Int16(p^);
  445.               4: Result := Int32(p^);
  446.             end;
  447.           end;
  448.         SRVBIT: Result := ByteBool(p^);
  449.         SRVDECIMAL,
  450.         SRVNUMERIC:
  451.           begin
  452.             FillChar(numeric, 0, SizeOf(DBNUMERIC));
  453.             Move(p^, numeric, paramlen);
  454.             l := 0;
  455.             Move(numeric.val, l, paramlen-3);
  456.             s := IntToStr(l);
  457.             System.Insert(DecimalSeparator, s, length(s) - numeric.scale + 1);
  458.             Result := StrToFloat(s);
  459.           end;
  460.         SRVFLTN:
  461.           begin
  462.             if paramlen = 4
  463.               then
  464.                 Result := single(p^)
  465.               else
  466.                 Result := double(p^);
  467.           end;
  468.         SRVMONEYN:
  469.           begin
  470.             if paramlen = 4
  471.               then  begin
  472.                 Move(p^, money4, paramlen);
  473.                 Result := money4 / 10000.0;
  474.               end
  475.               else  begin
  476.                 Move(p^, money, paramlen);
  477.                 dc := money.mnyhigh;
  478.                 dc := dc * $10000;
  479.                 dc := dc * $10000;
  480.                 if money.mnylow >= 0
  481.                   then  dc2 := money.mnylow
  482.                   else  begin
  483.                     dc2 := $10000;
  484.                     dc2 := dc2 * $10000;
  485.                     dc2 := dc2 + money.mnylow;
  486.                   end;
  487.                 dc := dc + dc2;
  488.                 Result := dc / 10000;
  489.               end;
  490.           end;
  491.         SRVDATETIMN:
  492.           begin
  493.             if paramlen = 8
  494.               then  begin
  495.                 Move(p^, dbdt, paramlen);
  496.                 dt := (dbdt.dtdays + 2) + (dbdt.dttime / (24*3600*300));
  497.               end
  498.               else  begin
  499.                 Move(p^, dbdt4, paramlen);
  500.                 dt := (dbdt4.numdays + 2) + (dbdt4.nummins / (24*60));
  501.               end;
  502.             Result := dt;
  503.           end;
  504.       else  begin
  505. {$IFDEF Debug}
  506.         BBWrite('srv_paramtype = ' + IntToStr(srv_paramtype(srvproc, Index)) + ' -- TSQLXProc.GetParam --');
  507. {$ENDIF}
  508.         Result := Null;
  509.       end;
  510.       end; { of case }
  511.     end;
  512. end;
  513.  
  514. function TSQLXProc.GetParamByName(Name: string): Variant;
  515. var
  516.   Index: integer;
  517. begin
  518.   Index := srv_paramnumber(srvproc,PChar(Name), SRV_NULLTERM);
  519.   Result := GetParam(Index);
  520. end;
  521.  
  522. function TSQLXProc.Run: SRVRETCODE;
  523. var
  524.   paramnum: integer;
  525.   ResultOK: Boolean;
  526.   s: string;
  527. begin
  528. { Check number of parameters }
  529.   paramnum := GetParamCount;
  530.   if (ExpectedParamCount <> -1) and
  531.      (paramnum <> ExpectedParamCount) then  begin
  532.     { Send error message and return }
  533.     srv_sendmsg(srvproc, SRV_MSG_ERROR, PARAM_ERROR, SRV_INFO, 0,
  534.                 nil, 0, 0, 'Error executing extended stored procedure: Invalid # of Parameters',
  535.                 SRV_NULLTERM);
  536.     { A SRV_DONE_MORE instead of a SRV_DONE_FINAL must complete the
  537.       result set of an Extended Stored Procedure. }
  538.     srv_senddone(srvproc, (SRV_DONE_ERROR or SRV_DONE_MORE), 0, 0);
  539.     Result := FAIL;
  540.     Exit;
  541.   end;
  542.  
  543.   try
  544.     ResultOK := Execute;
  545.   except
  546.     on E:Exception do  begin
  547.       ResultOK := False;
  548.       s := 'Execution interrupted by exception: ' + E.Message;
  549.       srv_sendmsg(srvproc, SRV_MSG_ERROR, 0, SRV_FATAL_PROCESS, 0, nil, 0, 0, PChar(s), SRV_NULLTERM);
  550.     end;
  551.   end;
  552.  
  553. { send msg back depending on result }
  554.   if ResultOK
  555.     then  begin
  556.       if RowCount > 0
  557.         then
  558.           srv_senddone(srvproc, SRV_DONE_COUNT or SRV_DONE_MORE, 0, RowCount)
  559.         else
  560.           srv_senddone(srvproc, SRV_DONE_MORE, 0, 0);
  561.       Result := SUCCEED;
  562.     end
  563.     else  begin
  564.       srv_senddone(srvproc, (SRV_DONE_ERROR or SRV_DONE_MORE), 0, 0);
  565.       Result := FAIL;
  566.     end;
  567. end;
  568.  
  569.  
  570. procedure TSQLXProc.SendErrorMsg(const Msg: string);
  571. begin
  572.   srv_sendmsg(srvproc, SRV_MSG_ERROR, 0, SRV_INFO, 0, nil, 0, 0, PChar(Msg), SRV_NULLTERM);
  573. end;
  574.  
  575.  
  576. procedure TSQLXProc.SendInfoMsg(const Msg: string);
  577. begin
  578.   srv_sendmsg(srvproc, SRV_MSG_INFO, 0, SRV_INFO, 0, nil, 0, 0, PChar(Msg), SRV_NULLTERM);
  579. end;
  580.  
  581.  
  582. procedure TSQLXProc.SetParam(Index: integer; const Value: Variant);
  583.  
  584.   function valsize(l: longint): integer;
  585.   begin
  586.     if l < $100
  587.       then  Result := 1
  588.       else  if l < $10000
  589.       then  Result := 2
  590.       else  if l < $1000000
  591.       then  Result := 3
  592.       else  Result := 4;
  593.   end;
  594.  
  595. var
  596.   dest: array[0..DBMAXCHAR] of AnsiChar;
  597.   di: integer;
  598.   ds: single;
  599.   dd: double;
  600.   parammaxlen: integer;
  601.   s: string;
  602.   l: longint;
  603.   numeric: DBNUMERIC;
  604.   p: word;
  605.   b: ByteBool;
  606.   dt: TDateTime;
  607.   dbdt: DBDATETIME;
  608.   dbdt4: DBDATETIM4;
  609.   money4: DBMONEY4;
  610.   money: DBMONEY;
  611.   curint: comp;
  612.   dc: comp;
  613. begin
  614.   parammaxlen := srv_parammaxlen(srvproc, Index);
  615. {$IFDEF Debug}
  616.   BBWrite('parammaxlen = ' + IntToStr(parammaxlen) + ' -- TSQLXProc.SetParam --');
  617. {$ENDIF}
  618.   if Value = Null
  619.     then  begin
  620.       srv_paramset(srvproc, Index, nil, 0);
  621.     end
  622.     else  begin
  623.       case srv_paramtype(srvproc, Index) of
  624.         SRVVARCHAR,
  625.         SRVCHAR: srv_paramset(srvproc, Index, StrPCopy(dest, Value), length(Value));
  626.         SRVINTN:
  627.           begin
  628.             di := Value;
  629.             srv_paramset(srvproc, Index, @di, parammaxlen);
  630.           end;
  631.         SRVBIT:
  632.           begin
  633.             b := Value;
  634.             srv_paramset(srvproc, Index, @b, SizeOf(ByteBool));
  635.           end;
  636.         SRVDECIMAL,
  637.         SRVNUMERIC:
  638.           begin
  639.             s := FloatToStr(Value);
  640.             p := Pos(DecimalSeparator, s);
  641.             if p = 0 then  begin
  642.               s:= s + DecimalSeparator + '0';
  643.               p := Pos(DecimalSeparator, s);
  644.             end;
  645.             System.Delete(s, p, 1);
  646.             l := StrToInt(s);
  647.             FillChar(numeric, 0, SizeOf(DBNUMERIC));
  648.             Move(l, numeric.val, SizeOf(l));
  649.             numeric.sign := Value > 0;
  650.             numeric.precision := length(s);
  651.             numeric.scale := numeric.precision - p + 1;
  652.             srv_paramset(srvproc, Index, @numeric, 3 + valsize(l));
  653.           end;
  654.         SRVFLTN:
  655.           begin
  656.             if parammaxlen = 4
  657.               then  begin
  658.                 ds := Value;
  659.                 srv_paramset(srvproc, Index, @ds, SizeOf(ds));
  660.               end
  661.               else  begin
  662.                 dd := Value;
  663.                 srv_paramset(srvproc, Index, @dd, SizeOf(dd));
  664.               end;
  665.           end;
  666.         SRVMONEYN:
  667.           begin
  668.             if parammaxlen = 4
  669.               then  begin
  670.                 money4 := Value * 10000;
  671.                 srv_paramset(srvproc, Index, @money4, SizeOf(money4));
  672.               end
  673.               else  begin
  674.                 curint := Value * 10000;
  675.                 dc := curint / $10000;
  676.                 dc := dc / $10000;
  677.                 money.mnyhigh := Round(dc);
  678.                 dc := dc * $10000;
  679.                 dc := dc * $10000;
  680.                 money.mnylow := Round(curint - dc);
  681.                 if money.mnylow < 0 then
  682.                   Dec(money.mnyhigh);
  683.                 srv_paramset(srvproc, Index, @money, SizeOf(money));
  684.               end;
  685.           end;
  686.         SRVDATETIMN:
  687.           begin
  688.             dt := Value;
  689.             if parammaxlen = 8
  690.               then  begin
  691.                 dbdt.dtdays := Round(Int(dt)) - 2;
  692.                 dbdt.dttime := Round(Frac(dt) * (24*3600*300));
  693.                 srv_paramset(srvproc, Index, @dbdt, SizeOf(dbdt));
  694.               end
  695.               else  begin
  696.                 dbdt4.numdays := Round(Int(dt)) - 2;
  697.                 dbdt4.nummins := Round(Frac(dt) * (24*60));
  698.                 srv_paramset(srvproc, Index, @dbdt4, SizeOf(dbdt4));
  699.               end;
  700.           end;
  701.       else  begin
  702.         srv_paramset(srvproc, Index, nil, 0);
  703.       {$IFDEF Debug}
  704.         BBWrite('srv_paramtype = ' + IntToStr(srv_paramtype(srvproc, Index)) + ' -- TSQLXProc.SetParam');
  705.       {$ENDIF}
  706.       end;
  707.       end; { of case }
  708.     end;
  709. end;
  710.  
  711.  
  712. procedure TSQLXProc.SetParamByName(Name: string; const Value: Variant);
  713. var
  714.   Index: integer;
  715. begin
  716.   Index := srv_paramnumber(srvproc,PChar(Name), SRV_NULLTERM);
  717.   SetParam(Index, Value);
  718. end;
  719.  
  720.  
  721. procedure TSQLXProc.SendRow;
  722. begin
  723.   if srv_sendrow(srvproc) = SUCCEED then
  724.     Inc(RowCount);
  725. end;
  726.  
  727.  
  728. end.
  729.  
  730.